package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

@Service
public class DishServiceImpl implements DishService {
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private DishFlavorMapper dishFlavorMapper;
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;
    @Autowired
    private CategoryMapper categoryMapper;

    /*
     *
     * 新增菜品
     *
     * */
    @Override
    @Transactional
    public void saveWithFlavor(DishDTO dishDTO) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        //向菜品插入数据
        dishMapper.insert(dish);
        //获取xml文件中生成的主键值
        Long dishId = dish.getId();
        //插入多个口味
        List<DishFlavor> flavors = dishDTO.getFlavors();
        //判断dishDTO中封装的flavor集合中是否有数据
        if (flavors != null && !flavors.isEmpty()) {
            //给集合中的口味添加归属的菜品dish_id
            flavors.forEach(flavor -> {
                flavor.setDishId(dishId);
            });
            //向口味表插入多个数据
            dishFlavorMapper.insertFlavor(flavors);
        }
    }

    /*
     *
     * 分页查询
     * 根据类型查询分类名称
     *
     * */
    @Override
    public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dishPageQueryDTO, dishVO);
        Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
        //获取菜品分类id，根据id查询菜品名称
        return new PageResult(page.getTotal(), page.getResult());
    }


    /*
     *
     * 批量删除菜品
     *
     * */
    @Override
    public void deleteBatch(List<Long> ids) {
        //判断当前菜品的状态:
        //条件1： 起售中不可删除，
        for (Long id : ids) {
            //查询对应id的全部数据
            Dish dish = dishMapper.getById(id);
            if (dish.getStatus() == StatusConstant.ENABLE) {
                //判断条件1
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }
        //条件2： 菜品关联套餐不可删除
        List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
        if (setmealIds != null && !setmealIds.isEmpty()) {
            //判断条件2
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        //满足条件
        //删除菜品表中的数据
        //dishMapper.delete(id);
        //删除菜品对应的口味数据
        //dishFlavorMapper.deleteByDishId(id);

        //优化：根据ids集合批量删除数据，不在去遍历一次，执行一条SQL语句
        dishMapper.deleteByIds(ids);
        dishFlavorMapper.deleteByIds(ids);

        // 关联其他表也不能删除


    }

    /*
     *
     * 根据id查询菜品
     *
     * */
    @Override
    public DishVO listById(Long id) {
        //方案一：(还行)
        Dish dish = dishMapper.getById(id);
        List<DishFlavor> listFlavor = dishFlavorMapper.getById(id);
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish, dishVO);
        dishVO.setFlavors(listFlavor);

        /*方案二：(不推荐)
        DishVO dishVO = dishMapper.listById(id);
        List<DishFlavor> listFlavor =  dishFlavorMapper.getById(id);
        dishVO.setFlavors(listFlavor);*/

        // Mapper 层使用关联查询（伪代码）
        /*方案三(优化)
        @Select("SELECT d.*, df.* FROM dish d 0LEFT JOIN dish_flavor df ON d.id = df.dish_id WHERE d.id=#{id}")
        @Results({
                @Result(property = "flavors", column = "id", many = @Many(select = "getDishFlavors"))
        })*/
        return dishVO;
    }

    /*
     *
     * 修改菜品(根据id)
     *
     * */
    @Override
    @Transactional//事务注解
    public void updateDishAndFlavor(DishDTO dishDTO) {
        //如果直接将dishDTO传进去,会携带着口味数据
        //将dishDTO的基本数据传进去
        //从设计层面更加合理
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        //修改菜品表
        dishMapper.update(dish);
        //修改口味表：方案一：先把原先的口味数据全部数据，然后再插入
        dishFlavorMapper.deleteById(dishDTO.getId());
        //插入之前还要判断一下原来有没有口味数据，如果没有就跳过(减少SQL操作)
        List<DishFlavor> flavorList = dishDTO.getFlavors();
        Long dishId = dishDTO.getId();
        //重新插入的时候前端不一定会把dishId传过来
        if (flavorList != null && !flavorList.isEmpty()) {
            //给集合中的口味添加归属的菜品dish_id
            flavorList.forEach(flavor -> {
                flavor.setDishId(dishId);
            });
            //向口味表插入多个数据
            dishFlavorMapper.insertFlavor(flavorList);
        }
    }

    @Override
    public void startOrStop(Integer status, Integer id) {
        //逻辑分析
        //1.根据id修改菜品表状态
        dishMapper.startOrStop(status, id);
        //2.根据前端传来的参数是true/false来对菜品关联的套餐表进行相同的状态改变
        List<BigInteger> setmealIdList = setmealDishMapper.getSetmealIdsByDishId(id);
        if (status.equals(StatusConstant.ENABLE)) {
            //起售
            //判断是否关联有菜品(默认都没有关联)
            //根据dishId查询setmeal_dish表中的setmeal_id,返回一个集合，
            // 然后判断集合是否为空，如果为空则放行，反之根据setmeal_id对setmeal中的套餐进行对应的状态修改
            if (setmealIdList != null && !setmealIdList.isEmpty()) {
                //不为空：根据setmeal_id对setmeal中的套餐进行对应的状态修改
                //遍历所有关联的套餐
                setmealIdList.forEach(setmealId -> {
                    setmealMapper.startOrStop(status, setmealId);
                });

            }
        } else if (status.equals(StatusConstant.DISABLE)) {
            if (setmealIdList != null && !setmealIdList.isEmpty()) {
                //不为空：根据setmeal_id对setmeal中的套餐进行对应的状态修改
                setmealIdList.forEach(setmealId -> {
                    setmealMapper.startOrStop(status, setmealId);
                });
            }
        }

    }

    /**
     * 根据分类id查询菜品
     *
     * @param categoryId
     * @return
     */
    public List<Dish> list(Long categoryId) {
        Dish dish = Dish.builder()
                .categoryId(categoryId)
                .status(StatusConstant.ENABLE)
                .build();
        return dishMapper.list(dish);
    }

    /*
     *
     * 根据分类id查询菜品
     *
     * */
/*    @Override
    public List<DishVO> listByCategoryId(Long categoryId) {
        //根据分类id查询菜品和菜品的口味
        List<Dish> dishlist = dishMapper.listByCategoryId(categoryId);
        //根据分类id获取分类名称
        String name = categoryMapper.getNameByCategoryId(categoryId);
        //将数据封装进DishVO
        List<DishVO> dishVOList = new ArrayList<>();
        for (Dish dish : dishlist) {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(dish, dishVO);
            dishVO.setName(name);
            dishVOList.add(dishVO);
            List<DishFlavor> flavors = dishFlavorMapper.getByDishId(dish.getId());
            dishVO.setFlavors(flavors);
        }
        return dishVOList;
    }*/

    /**
     * 条件查询菜品和口味
     * @param dish
     * @return
     */
    public List<DishVO> listWithFlavor(Dish dish) {
        List<Dish> dishList = dishMapper.list(dish);

        List<DishVO> dishVOList = new ArrayList<>();

        for (Dish d : dishList) {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(d,dishVO);

            //根据菜品id查询对应的口味
            List<DishFlavor> flavors = dishFlavorMapper.getByDishId(d.getId());
            dishVO.setName(d.getName());
            dishVO.setFlavors(flavors);
            dishVOList.add(dishVO);
        }

        return dishVOList;
    }


}
